# -*- coding: utf-8 -*-
"""
Author: chen xi
Date: 2025/5/6 上午11:39
File: adjacency_list_excel_manager.py

该脚本提供了一个处理Excel文件中邻接表数据的类AdjacencyListHandler，
以及一些辅助函数来操作这些数据。
"""

import pandas as pd


class AdjacencyListExcelManager:
	# 定义数据类型的字典，用于pandas读取Excel时指定列的数据类型
	data_types = {'raw': str, '置信度': int}
	
	def __init__(self, file_path, sheet_name):
		"""
		初始化AdjacencyListExcelManager实例。

		:param file_path: Excel文件路径
		:param sheet_name: 要读取的工作表名称
		"""
		self.file_path = file_path
		self.sheet_name = sheet_name
		self.data_frame = self.get_data_frame()  # 获取并处理Excel数据为DataFrame
		self.al_data_frame = self.filter_adjacent_vertices()  # 过滤得到非空第二列的DataFrame
	
	def get_data_frame(self) -> pd.DataFrame:
		"""
		从指定的Excel文件和工作表读取数据，并进行初步处理。

		:return: 返回一个经过清理后的DataFrame对象
		"""
		df = pd.read_excel(self.file_path, sheet_name=self.sheet_name, dtype=self.data_types)
		# 去除索引并过滤掉所有以'Unnamed:'开头的列
		df_reset = df.reset_index(drop=True)
		df_filtered = df_reset.loc[:, ~df.columns.str.startswith('Unnamed:')]
		return df_filtered
	
	def filter_adjacent_vertices(self) -> pd.DataFrame:
		"""
		进一步过滤data_frame，保留第二列非空的所有行。

		:return: 返回过滤后的DataFrame
		"""
		non_null_rows = self.data_frame.iloc[:, 1].notnull()
		df_filtered = self.data_frame[non_null_rows]
		df_final = df_filtered.loc[:, ~df_filtered.columns.str.startswith('Unnamed:')]
		return df_final
	
	def get_page_names(self) -> set:
		"""
		提取DataFrame中第一列的所有唯一值作为页面节点名。

		:return: 包含所有页面节点名的集合
		"""
		return set(self.data_frame.iloc[:, 0])
	
	def get_edges(self) -> dict:
		"""
		根据al_data_frame构建边的集合，每条边由第一列和第二列的值组成。

		:return: 包含边及其对应记录的字典
		"""
		edges = {}
		for index, row in self.al_data_frame.iterrows():
			value1, value2 = row.iloc[0], row.iloc[1]
			if value2 is not None and value1 is not None:
				key = (value1, value2)
				if key not in edges:
					edges[key] = [self.al_data_frame.to_dict('records')[index]]
				else:
					edges[key].append(self.al_data_frame.to_dict('records')[index])
		return edges
	
	def read_all_elements_from_excel(self) -> dict:
		"""
		将Excel中的元素按页面名称组织成嵌套字典结构。

		:return: 按页面名称分组的嵌套字典
		"""
		page_elements_dict = {}
		df = self.data_frame
		al_list = df.to_dict('records')
		for index, row in df.iterrows():
			page_name = row.iloc[0]
			if not page_name:
				continue
			if page_name not in page_elements_dict:
				page_elements_dict[page_name] = [al_list[index]]
			else:
				page_elements_dict[page_name].append(al_list[index])
		return page_elements_dict


def write_element_to_excel(new_data, file_path, sheet_name):
	"""
	将新数据追加到现有的Excel文件中。

	:param new_data: 新增的数据（DataFrame格式）
	:param file_path: 目标Excel文件路径
	:param sheet_name: 工作表名称
	"""
	existing_df = pd.read_excel(file_path, sheet_name=sheet_name)
	combined_df = pd.concat([existing_df, new_data], ignore_index=True)
	combined_df.to_excel(file_path, sheet_name=sheet_name, index=False)


def pad_dict_values_to_max_length(d, fill_value=None):
	"""
	将字典中每个列表值补齐到最大长度。

	:param d: 输入字典
	:param fill_value: 用于补齐的值，默认为None
	:return: 键对应的值被补齐到最大长度的新字典
	"""
	max_length = max(len(value) for value in d.values())
	padded_dict = {k: v + [fill_value] * (max_length - len(v)) for k, v in d.items()}
	return padded_dict


def filter_df_and_write_excel(df: pd.DataFrame, filter_column: str, filter_value: str, output_file: str,
                              sheet_name: str):
	"""
	筛选DataFrame中指定列不等于filter_value的行，并将结果写入新的Excel文件。

	:param df: 要筛选的DataFrame
	:param filter_column: 筛选条件所依据的列名
	:param filter_value: 不等于此值的行将被保留
	:param output_file: 输出文件路径
	:param sheet_name: 输出文件的工作表名称
	"""
	filtered_df = df.loc[df[filter_column] != filter_value]
	write_element_to_excel(filtered_df, output_file, sheet_name=sheet_name)


if __name__ == '__main__':
	al = AdjacencyListExcelManager(
		file_path=r"C:\Users\Administrator\uiauto2\UiAutoTest\config\睿博士.xlsx",
		sheet_name="置信表"
	)
	#
	# print(al.al_data_frame.to_dict('records'))
	# print(al.al_data_frame.columns)
	# print(al.get_page_names())
	# _driver = al.get_edges()
	# print(_driver[('首页', '蓝牙搜索')])
	print(al.read_all_elements_from_excel())
	# 创建一个简单的DataFrame
